在iOS上使用ML Kit识别图像中的文本

您可以使用ML Kit来识别图像中的文本,使用设备上的模型或云上的模型。请参阅概述以了解每种方法的优点。

有关此API使用的示例,请参阅GitHub上的ML Kit快速入门示例,或者尝试使用codelab

在您开始之前

  1. 如果您还没有将Firebase添加到您的程序当中,那您可以从开始指南来开始您的工作。

  2. 将ML kit库放进您的Podfile中:

    1. pod 'Firebase/Core'
    2. pod 'Firebase/MLVision'
    3. # If using the on-device API:
    4. pod 'Firebase/MLVisionTextModel'

​ 而后每次您要安装或者升级您的Pods的时候,请确保使用您的Xcode项目的.xcworkspace来打开它。

  1. 在您的程序中,引入Firebase:

    Swift:

    1. import Firebase

    Objective-C:

    1. @import Firebase;
  2. 如果您想使用基于云的模型,并且尚未将项目升级到Blaze计划,请在Firebase控制台中执行此操作。只有Blaze计划的项目才能使用Cloud Vision API。

  3. 如果您想使用基于云的模型,您也需要开启Cloud Vision API:

    • 在云API列表管理平台中打开Cloud Vision API
    • 确保您的Firebase项目已经在当前菜单页面中被置于顶端。
    • 如果API依旧还是显示为enabled,请点击Enable。

    如果您想要仅仅开启使用设备上的模型,您可以跳过这一步。

现在您已经可以开始使用设备上的模型或者基于云端的模型识别图像中的文本了。

在设备上识别文本

为了使用设备上的文本识别模型,请运行如下文本识别器。

  1. 运行文本识别器

    为了能够识别图像中的文本,将图像传递为UIImage或者CMSampleBufferRefVisionTextDetectordetect(in:)方法:

    1. 得到一个VisionTextDetector实例:

      Swift:

      1. lazy var vision = Vision.vision()
      2. let textDetector = vision.textDetector() // 检测错误.

      Objective-C:

      1. FIRVision *vision = [FIRVision vision];
      2. FIRVisionTextDetector *detector = [vision textDetector];
    2. 使用UIImage或者CMSampleBufferRef创建一个VisionImage对象:

      使用UIImage

      1. 如有必要,旋转图像以使其imageOrientation 属性为.up

      2. VisionImage使用正确旋转的对象创建一个对象 UIImage。不要指定任何旋转元数据 - 默认值.topLeft,必须使用。

        Swift:

        1. let image = VisionImage(image: uiImage)

        Objective-C:

        1. FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

      使用CMSampleBufferRef

      1. 创建一个VisionImageMetadata对象,该对象指定包含在CMSampleBufferRef缓冲区中的图像数据的方向 。

        例如,如果图像数据必须顺时针旋转90度才能保持直立:

        Swift:

        1. let metadata = VisionImageMetadata()
        2. metadata.orientation = .rightTop // Row为0在右边,column为0则是在顶端

        Objective-C:

        1. // Row为0在右边,column为0则是在顶端
        2. FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
        3. metadata.orientation = FIRVisionDetectorImageOrientationRightTop;
      2. VisionImage使用CMSampleBufferRef对象和旋转元数据创建一个对象 :

        Swift:

        1. let image = VisionImage(buffer: bufferRef)
        2. image.metadata = metadata

        Objective-C:

        1. FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:buffer];
        2. image.metadata = metadata;
    3. 然后,将图像传递给该detect(in:)方法:

      Swift:

      1. textDetector.detect(in: visionImage) { (features, error) in
      2. guard error == nil, let features = features, !features.isEmpty else {
      3. //错误,您应该检查控制台来寻找错误
      4. // ...
      5. return
      6. }
      7. // 识别并且输出文本
      8. print("Detected text has: \(features.count) blocks")
      9. // ...
      10. }

      Objective-C:

      1. [detector detectInImage:image
      2. completion:^(NSArray<FIRVisionText *> *features,
      3. NSError *error) {
      4. if (error != nil) {
      5. return;
      6. } else if (features != nil) {
      7. // Recognized text
      8. }
      9. }];
  2. 从识别的文本块中提取文本

    如果文本识别操作成功,它将返回一个VisionText对象数组 。每个VisionText对象都代表一个矩形的文本块,一行文本或一个文本单词。

    对于每一个VisionText,您都可以获取块的边界坐标和块中包含的文本:

    Swift:

    1. for feature in features {
    2. let value = feature.text
    3. let corners = feature.cornerPoints
    4. }

    Objective-C:

    1. for (id <FIRVisionText> feature in features) {
    2. NSString *value = feature.text;
    3. NSArray<NSValue *> *corners = feature.cornerPoints;
    4. }

    另外,如果VisionText,是VisionTextBlock,你可以得到构成块的文本行,如果是 VisionTextLine,你可以得到组成每行文本的元素:

    Swift:

    1. // 内含文本列的块
    2. if let block = feature as? VisionTextBlock {
    3. for line in block.lines {
    4. // ...
    5. for element in line.elements {
    6. // ...
    7. }
    8. }
    9. }
    10. // 包含文本元素的Lines
    11. else if let line = feature as? VisionTextLine {
    12. for element in line.elements {
    13. // ...
    14. }
    15. }
    16. // 文本元素都是可输出文本
    17. else if let element = feature as? VisionTextElement {
    18. // ...
    19. }

    Objective-C:

    1. // 内含文本列的块
    2. if ([feature isKindOfClass:[FIRVisionTextBlock class]]) {
    3. FIRVisionTextBlock *block = (FIRVisionTextBlock *)feature;
    4. for (FIRVisionTextLine *line in block.lines) {
    5. // ...
    6. for (FIRVisionTextElement *element in line.elements) {
    7. // ...
    8. }
    9. }
    10. }
    11. // 包含文本元素的Lines
    12. else if ([feature isKindOfClass:[FIRVisionTextLine class]]) {
    13. FIRVisionTextLine *line = (FIRVisionTextLine *)feature;
    14. for (FIRVisionTextElement *element in line.elements) {
    15. // ...
    16. }
    17. }
    18. // 文本元素都是可输出文本
    19. else if ([feature isKindOfClass:[FIRVisionTextElement class]]) {
    20. // ...
    21. }

    基于云端的文本识别

要使用基于云的文本识别模型,请配置并运行文本识别器,如下所述。

ML Kit的基于云的API目前仅可用于预览。对于投入生产的基于云的API,请考虑直接使用Cloud Vision API。

  1. 配置文本识别器

    默认情况下,云检测器使用稳定版本的模型。如果您想要使用最新版本的模型,请按照以下示例创建一个VisionCloudDetectorOptions对象:

    Swift:

    1. let options = VisionCloudDetectorOptions()
    2. options.modelType = .latest
    3. // options.maxResults 对此API没有任何影响

    Objective-C:

    1. FIRVisionCloudDetectorOptions *options =
    2. [[FIRVisionCloudDetectorOptions alloc] init];
    3. options.modelType = FIRVisionCloudModelTypeLatest;

    在下一步中,VisionCloudDetectorOptions创建Cloud识别器对象时传递该对象。

  2. 运行文本识别器

    要识别图像中的文本,请创建一个VisionCloudTextDetector对象,或者,如果图像是文档,则为VisionCloudDocumentTextDetector对象。然后,将图像作为UIImage或传递CMSampleBufferRef给该detectText(in:) 方法:

    1. 获取VisionCloudTextDetectorVisionCloudDocumentTextDetector的实例:

      Swift:

      1. lazy var vision = Vision.vision()
      2. let textDetector = vision.cloudTextDetector(options: options)
      3. // 或者用默认设置:
      4. // let textDetector = vision?.cloudTextDetector()

      Objective-C:

      1. FIRVision *vision = [FIRVision vision];
      2. FIRVisionCloudTextDetector *detector = [vision cloudTextDetector];
      3. // 或者更改默认设置:
      4. // FIRVisionCloudTextDetector *detector =
      5. // [vision cloudTextDetectorWithOptions:options];
    2. VisionImage使用UIImage或 创建一个对象CMSampleBufferRef

      使用UIImage

      1. 如有必要,旋转图像以使其imageOrientation 属性为.up

      2. VisionImage使用正确旋转的对象创建一个对象 UIImage。不要指定任何旋转元数据 - 默认值.topLeft,必须使用。

        Swift:

        1. let image = VisionImage(image: uiImage)

        Objective-C:

        1. FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

      使用CMSampleBufferRef

      1. 创建一个VisionImageMetadata对象,该对象指定包含在CMSampleBufferRef缓冲区中的图像数据的方向 。

        例如,如果图像数据必须顺时针旋转90度才能保持直立:

        Swift:

        1. let metadata = VisionImageMetadata()
        2. metadata.orientation = .rightTop // Row为0在右边,column为0则是在顶端

        Objective-C:

        1. // Row为0在右边,column为0则是在顶端
        2. FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
        3. metadata.orientation = FIRVisionDetectorImageOrientationRightTop;
      2. VisionImage使用CMSampleBufferRef对象和旋转元数据创建一个对象 :

        Swift:

        1. let image = VisionImage(buffer: bufferRef)
        2. image.metadata = metadata

        Objective-C:

        1. FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:buffer];
        2. image.metadata = metadata;
    3. 然后,将图像传递给该detect(in:)方法:

      Swift:

      1. textDetector.detect(in: visionImage) { (cloudText, error) in
      2. guard error == nil, let cloudText = cloudText else {
      3. // ...
      4. return
      5. }
      6. // 识别并且输出文本
      7. // ...
      8. }

      Objective-C:

      1. [detector detectInImage:image
      2. completion:^(FIRVisionCloudText *cloudText,
      3. NSError *error) {
      4. if (error != nil) {
      5. return;
      6. } else if (cloudText != nil) {
      7. // Recognized text
      8. }
      9. }];
  3. 从识别的文本块中提取文本

    如果文本识别操作成功,则会将VisionCloudText对象传递给成功侦听器(Success Listener)。该对象包含图像中识别的文本。

    例如:

    Swift

    1. let recognizedText = cloudText.text

    Objective-C:

    1. NSString *recognizedText = cloudText.text;

    您还可以获取有关文本结构的信息。文本被组织成页面,块,段落,单词和符号。对于组织的每个单位,您都可以获取信息,例如其维度及其包含的语言。

    例如:

    Swift:

    1. for page in cloudText.pages {
    2. let width = page.width
    3. let height = page.height
    4. let langs = page.textProperty?.detectedLanguages
    5. if let blocks = page.blocks {
    6. for block in blocks {
    7. let blockFrame = block.frame
    8. }
    9. }
    10. }

    Objective-C:

    1. for (FIRVisionCloudPage *page in cloudText.pages) {
    2. int width = [page.width intValue];
    3. int height = [page.height intValue];
    4. NSArray<FIRVisionCloudDetectedLanguage *> *langs = page.textProperty.detectedLanguages;
    5. for (FIRVisionCloudBlock *block in page.blocks) {
    6. CGRect frame = block.frame;
    7. // 等等.
    8. }
    9. }